package com.rongji.cms.tools.temp.test;

/**
 * @author yang
 * @date 2023/2/23 14:17
 * @description
 */

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class DFAFilter {
    private Set<Character> sensitiveChars;  // 敏感字符集合
    private Map<Integer, Map<Character, Integer>> dfa;  // DFA自动机

    /**
     * 构造函数，传入敏感词列表，构建DFA自动机
     * @param sensitiveWords 敏感词列表
     */
    public DFAFilter(Set<String> sensitiveWords) {
        // 初始化敏感字符集合
        sensitiveChars = new HashSet<>();
        for (String word : sensitiveWords) {
            for (char c : word.toCharArray()) {
                sensitiveChars.add(c);
            }
        }

        // 初始化DFA自动机
        dfa = new HashMap<>();
        int stateCount = 0;  // 状态数量
        for (String word : sensitiveWords) {
            int state = 0;  // 当前状态
            for (char c : word.toCharArray()) {
                Map<Character, Integer> trans = dfa.computeIfAbsent(state, k -> new HashMap<>());
                int next = trans.getOrDefault(c, 0);
                if (next == 0) {
                    next = ++stateCount;
                    trans.put(c, next);
                }
                state = next;
            }
            Map<Character, Integer> trans = dfa.computeIfAbsent(state, k -> new HashMap<>());
            trans.put((char) 0, -1);  // 标记为结束状态
        }
    }

    /**
     * 过滤敏感词，将敏感词替换为指定的替换符号
     * @param text 待过滤文本
     * @param replacement 替换符号
     * @return 过滤后的文本
     */
    public String filter(String text, char replacement) {
        StringBuilder result = new StringBuilder();  // 存放过滤后的结果
        int state = 0;  // DFA的初始状态为0
        for (int i = 0; i < text.length(); i++) {
            char c = text.charAt(i);
            if (!sensitiveChars.contains(c)) {
                // 如果当前字符不是敏感字符，则直接加入结果字符串中
                result.append(c);
                state = 0;  // 回到DFA的初始状态
            } else {
                // 如果当前字符是敏感字符，则根据DFA的转移规则转移到下一个状态
                Map<Character, Integer> transitions = dfa.get(state);
                if (transitions == null || !transitions.containsKey(c)) {
                    // 如果当前状态没有对应的转移，则回到DFA的初始状态
                    result.append(c);
                    state = 0;
                } else {
                    // 否则转移到下一个状态，并将替换字符加入结果字符串中
                    state = transitions.get(c);
                    result.append(replacement);
                }
            }
        }
        return result.toString();
    }

    public static void main(String[] args) {
        // 构造敏感词列表
        Set<String> sensitiveWords = new HashSet<>();
        sensitiveWords.add("三级片");
        sensitiveWords.add("fuck");

        // 构造DFAFilter对象
        DFAFilter filter = new DFAFilter(sensitiveWords);

        // 进行敏感词过滤
        String text = "这是一段文本，包含敏感词三级片和fuck，还有一个不敏感的词汇。";
        String filteredText = filter.filter(text, '*');
        System.out.println(filteredText);
    }
}

